<template><div><h2 id="csrf-保护" tabindex="-1"><a class="header-anchor" href="#csrf-保护"><span>CSRF 保护</span></a></h2>
<p>Laravel 6 中文文档 /</p>
<p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="csrf-protection" tabindex="-1"><a class="header-anchor" href="#csrf-protection"><span>CSRF Protection</span></a></h2>
<ul>
<li><a href="#csrf-introduction">介绍</a></li>
<li><a href="#csrf-excluding-uris">CSRF - 白名单</a></li>
<li><a href="#csrf-x-csrf-token">X-CSRF-Token</a></li>
<li><a href="#csrf-x-xsrf-token">X-XSRF-Token</a></li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p>Laravel 可以轻松使地保护你的应用程序免受 <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank" rel="noopener noreferrer">跨站请求伪造</a> (CSRF) 攻击。 跨站点请求伪造是一种恶意攻击，它凭借已通过身份验证的用户身份来运行未经过授权的命令。</p>
<p>Laravel 会自动为每个活跃的用户的会话生成一个 CSRF「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。</p>
<p>无论何时，当您在应用程序中定义 HTML 表单时，都应该在表单中包含一个隐藏的 CSRF 标记字段，以便 CSRF 保护中间件可以验证该请求，你可以使用 <code v-pre>@csrf</code> Blade 指令来生成令牌字段，如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>form method<span class="token operator">=</span><span class="token string double-quoted-string">"POST"</span> action<span class="token operator">=</span><span class="token string double-quoted-string">"/profile"</span><span class="token operator">></span></span>
<span class="line">    @csrf</span>
<span class="line">    <span class="token operator">...</span></span>
<span class="line"><span class="token operator">&lt;</span><span class="token operator">/</span>form<span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>包含在 <code v-pre>web</code> 中间件组里 <code v-pre>VerifyCsrfToken</code> <a href="https://learnku.com/docs/laravel/6.x/middleware" target="_blank" rel="noopener noreferrer">中间件</a>会自动验证请求里的令牌是否与存储在会话中令牌匹配。</p>
<h4 id="csrf-令牌-javascript" tabindex="-1"><a class="header-anchor" href="#csrf-令牌-javascript"><span>CSRF 令牌 &amp; JavaScript</span></a></h4>
<p>当构建由 JavaScript 驱动的应用时，可以方便的让 JavaScript HTTP<br>
函数库发起每一个请求时自动附上 CSRF 令牌。默认情况下，<code v-pre>resources/js/bootstrap.js</code>文件中提供的 Axios HTTP 库会使用 cookie 中加密的 <code v-pre>XSRF-TOKEN</code> 的值然后在请求时自动发送 <code v-pre>X-XSRF-TOKEN</code> 标头。 如果不使用此库，则需要为应用程序手动配置此行为。</p>
<h2 id="csrf-白名单" tabindex="-1"><a class="header-anchor" href="#csrf-白名单"><span>CSRF 白名单</span></a></h2>
<p>有时候你可能希望设置一组不需要的 CSRF 保护的 URL 。例如，如果你正在使用 <a href="https://stripe.com/" target="_blank" rel="noopener noreferrer">Stripe</a> 处理付款并使用了他们的 webhook 系统，你会需要从 CSRF 的保护中排除 Stripe webhook 处理程序路由，因为 Stripe 并不会给你的路由发送 CSRF 令牌。</p>
<p>典型做法，你可以把这类路由放在 <code v-pre>routes/web.php</code> 外，因为 <code v-pre>RouteServiceProvider</code> 的 <code v-pre>web</code> 中间件适用于该文件中的所有路由。不过，你也可以通过将这类 URL 添加到 <code v-pre>VerifyCsrfToken</code> 中间件的 <code v-pre>$except</code> 属性来排除对这类路由的 CSRF 保护，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>VerifyCsrfToken</span> <span class="token keyword">as</span> Middleware<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">VerifyCsrfToken</span> <span class="token keyword">extends</span> <span class="token class-name">Middleware</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 从CSRF验证中排除的URI</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$except</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'stripe/*'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'http://example.com/foo/bar'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'http://example.com/foo/*'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>Tip：当 <a href="https://learnku.com/docs/laravel/6.x/testing" target="_blank" rel="noopener noreferrer">运行测试</a> 时， CSRF 中间件会自动禁用。</p>
</blockquote>
<h2 id="x-csrf-token" tabindex="-1"><a class="header-anchor" href="#x-csrf-token"><span>X-CSRF-TOKEN</span></a></h2>
<p>除了检查 POST 参数中的 CSRF 令牌外， <code v-pre>VerifyCsrfToken</code> 中间件还会检查 <code v-pre>X-CSRF-TOKEN</code> 请求头。你应该将令牌保存在 HTML <code v-pre>meta</code> 标签中，如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>meta name<span class="token operator">=</span><span class="token string double-quoted-string">"csrf-token"</span> content<span class="token operator">=</span><span class="token string double-quoted-string">"{{ csrf_token() }}"</span><span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后，一旦你创建了 <code v-pre>meta</code> 标签，就可以指示像 jQuery 这样的库自动将令牌添加到所有请求的头信息中。还可以为基于 AJAX 的应用提供简单，方便的 CSRF 保护。如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">$<span class="token operator">.</span><span class="token function">ajaxSetup</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    headers<span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string single-quoted-string">'X-CSRF-TOKEN'</span><span class="token punctuation">:</span> $<span class="token punctuation">(</span><span class="token string single-quoted-string">'meta[name="csrf-token"]'</span><span class="token punctuation">)</span><span class="token operator">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'content'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="x-xsrf-token" tabindex="-1"><a class="header-anchor" href="#x-xsrf-token"><span>X-XSRF-TOKEN</span></a></h2>
<p>Laravel 将当前的 CSRF 令牌存储在一个 <code v-pre>XSRF-TOKEN</code> cookie<br>
中，该 cookie 包含在框架生成的每个响应中。你可以使用 cookie 值来设置 <code v-pre>X-XSRF-TOKEN</code> 请求头。</p>
<p>这个 cookie 主要是作为一种方便的方式发送的，因为一些 JavaScript 框架和库，例如 Angular 和 Axios ，会自动将它的值放入 <code v-pre>X-XSRF-TOKEN</code> 头中。</p>
<blockquote>
<p>Tip：默认情况下，<code v-pre>resources/js/bootstrap.js</code> 文件包含的 Axios HTTP 库，会自动为你发送。</p>
</blockquote>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/6.x/csrf/5137" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/6.x/csr...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/6.x/csrf/5137" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/6.x/csr...</a></p>
</blockquote>
</div></template>


